/******************************************************************************
 *  Include Files
 *****************************************************************************/
#include "DRV_PIT.h"
#include "DRV_FLASH.h"
#include "DRV_MSCAN.h"
#include "NVM.h"
#include "COM.h"
#include "Bootloader.h"

/******************************************************************************
 *  Macro Definitions
 *****************************************************************************/
#define Timeout_ms 10

/******************************************************************************
 *  Const Definitions
 *****************************************************************************/

/*****************************************************************************
 *  Global Variables Definitions
 *****************************************************************************/
static uint32_t StartTime = 0;

/*****************************************************************************
 *  Local Function declarations
 *****************************************************************************/
void JumpToUserApplication(uint32_t userStartup);

/*****************************************************************************
 *  Function Definitions
 *****************************************************************************/
int main(void) {
  // System Initialization
  SystemCoreClockUpdate();
  // Init
  DRV_FLASH_Init();
  DRV_PIT_Init();
  DRV_MSCAN_Init();
  COM_Init();

  StartTime = DRV_PIT_GetVal();
  NVM_Check_CheckSum();

  while (DRV_PIT_GetDiffTime_ms(StartTime) < Timeout_ms) {
    if (1 == COM_CheckLink()) {
      Bootloader_Main();
    }
  }

  while (0 == NVM_CHEKCSUM_OK) {
    StartTime = DRV_PIT_GetVal();
    while (DRV_PIT_GetDiffTime_ms(StartTime) < 100) {
      if (1 == COM_CheckLink()) {
        Bootloader_Main();
      }
    }
    COM_Send_Warning();
  }

  DRV_FLASH_DeInit();
  DRV_PIT_DeInit();
  DRV_MSCAN_DeInit();
  COM_DeInit();

	/* Check if a valid application is loaded and jump to it */
	SCB->VTOR = APP_START_ADDRESS;  
	JumpToUserApplication(APP_START_ADDRESS);
	//(*(void(*)(void))(*(uint32_t*) (APP_START_ADDRESS + 4)))();
  for (;;) {
  }
}

void JumpToUserApplication(uint32_t userStartup)
{
    /* set up stack pointer */  
    __asm("LDR     r1, [r0]");
    __asm("mov     r13, r1");
    /* jump to application reset vector */
    __asm("ADDS      r0,r0,#0x04 ");
    __asm("LDR      r0, [r0]");
    __asm("BX       r0");
}
